package com.dongdongshop.util;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.apache.catalina.manager.HTMLManagerServlet;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

@Component

public class SendSmsUtil {

    @Bean
    public SendSmsUtil getSendSmsUtil(){
        return new SendSmsUtil();
    }

    @Value("${aliyun.sms.accessKeyId}")
    private String accessKeyId;

    @Value("${aliyun.sms.accessKeySecret}")
    private String secret;

    @Value("${aliyun.sms.template_code}") // 模板id
    private String templateCode;

    @Value("${aliyun.sms.sign_name}") // 签名名称
    private String signName;

    private static final String DOMAIN = "dysmsapi.aliyuncs.com";
    private static final String VERSION = "2017-05-25";
    private static final String SEND_ACTION = "SendSms";
    private static final String REGION_ID = "cn-hangzhou";
    private static final String QUERY_ACTION = "QuerySendDetails";

    public String httpSendSms(String phoneNumbers,String checkCode) throws Exception {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        dateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));

        //系统参数
        Map<String,String> params = new HashMap<>();
        params.put("SignatureMethod","HMAC-SHA1");
        params.put("SignatureNonce", RandomStringUtils.randomNumeric(6));
        params.put("SignatureVersion","1.0");
        params.put("Timestamp", dateFormat.format(new Date()));
        params.put("AccessKeyId", accessKeyId);

        //业务API参数
        params.put("Action", SEND_ACTION);
        params.put("Version", VERSION);
        params.put("RegionId", REGION_ID);
        params.put("PhoneNumbers", phoneNumbers);
        params.put("SignName", signName);
        params.put("TemplateCode", templateCode);

        Map<String, String> map = new HashMap<>();
        map.put("sms_code", checkCode);
        String jsonCode = JSONObject.toJSONString(map);
        params.put("TemplateParam", jsonCode);

        //去除签名关键字Key
        if (params.containsKey("Signature"))
            params.remove("Signature");

        //参数Key的排序
        TreeMap<String,String> sortparas = new TreeMap<>(params);

        //构造代签名的字符串
        Iterator<String> iterator = sortparas.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (iterator.hasNext()) {
            String key = iterator.next();
            sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(params.get(key)));
        }
        // 去除第一个多余的&符号
        String sortedQueryString = sortQueryStringTmp.substring(1);

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("GET").append("&");
        stringBuilder.append(specialUrlEncode("/")).append("&");
        stringBuilder.append(specialUrlEncode(sortedQueryString));
        String sign = sign(secret + "&", stringBuilder.toString());

        //签名最后也要做URL特殊编码
        String signature = specialUrlEncode(sign);;
        // 最终打印出合法GET请求的URL
        String url = "http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp;

        return HttpClientUtil.doGet(url, null);
    }

    public static String sign(String accessSecret, String stringBuilder) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(new SecretKeySpec(accessSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringBuilder.getBytes(StandardCharsets.UTF_8));
        return new BASE64Encoder().encode(signData);
    }
    //构造待签名的请求串
    //一般的URLEncode后再增加三种字符替换：加号 （+）替换成 %20、星号 （*）替换成 %2A、 %7E 替换回波浪号 （~）
    public static String specialUrlEncode(String value) throws Exception {
        return URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }






    public String sendSms(String phoneNumbers,String checkCode) {
        //初始化
        DefaultProfile profile = DefaultProfile.getProfile(REGION_ID,accessKeyId, secret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setMethod(MethodType.POST);

        //产品域名,开发者无需替换
        request.setDomain(DOMAIN);
        request.setVersion(VERSION);
        request.setAction(SEND_ACTION);
        request.putQueryParameter("RegionId", REGION_ID);

        //必填:待发送手机号
        request.putQueryParameter("PhoneNumbers", phoneNumbers);

        //必填:短信签名-可在短信控制台中找到
        request.putQueryParameter("SignName", signName);

        //必填:短信模板-可在短信控制台中找到
        request.putQueryParameter("TemplateCode", templateCode);

        //sms_code是自己定义的
        Map<String, Object> map = new HashMap<>(6);
        map.put("sms_code", checkCode);
        String jsonCode = JSONObject.toJSONString(map);

        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        request.putQueryParameter("TemplateParam", jsonCode);

        //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
        request.putQueryParameter("OutId", "yourOutId");
        try {
            CommonResponse response = client.getCommonResponse(request);
            return response.getData();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String querySendDetails(String bizId, String phoneNumber) {
        DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, accessKeyId, secret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setMethod(MethodType.POST);

        //产品域名,开发者无需替换
        request.setDomain(DOMAIN);
        request.setVersion(VERSION);
        request.setAction(QUERY_ACTION);
        request.putQueryParameter("RegionId", REGION_ID);

        request.putQueryParameter("PhoneNumber", phoneNumber);
        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");
        request.putQueryParameter("SendDate", ft.format(new Date()));
        request.putQueryParameter("PageSize", "10");
        request.putQueryParameter("CurrentPage", "1");
        request.putQueryParameter("BizId", bizId);
        try {
            CommonResponse response = client.getCommonResponse(request);
            return response.getData();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return null;
    }
}